package com.datas.utils;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.json.JSONObject;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Component
public class JigeWebTools implements Serializable, ApplicationContextAware {

    public static ApplicationContext appContext = null;

    public void setApplicationContext(ApplicationContext arg0) throws BeansException {
        appContext = arg0;
    }

    public ApplicationContext getAppContext() {
        return appContext;
    }

    /**
     * @param datestr , endofday = false 00:00:00 endofday = true 23:59:59
     * @return Date
     */
    public static Date strToDate(String datestr, boolean endofday) {
        if (!datestr.trim().contains(" "))
            if (!endofday)
                datestr += " 00:00:00";
            else
                datestr += " 23:59:59";

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = null;
        try {
            date = format.parse(datestr);
        } catch (ParseException e) {
            LoggerFactory.getLogger(JigeWebTools.class).error("error", e);
        }
        return date;
    }

    /**
     * @param date
     * @param formate sample "yyyy-MM-dd HH:mm:ss"
     * @return
     */
    public static String formateDateCustom(Date date, String formate) {
        SimpleDateFormat dateformat = new SimpleDateFormat(formate);
        if (date == null) {
            return "";
        }
        return dateformat.format(date);
    }

    /**
     * @param date
     * @return "yyyy-MM-dd HH:mm:ss"
     */
    public static String formateDate(Date date) {
        SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (date == null) {
            return "";
        }
        return dateformat.format(date);
    }

    /**
     * @param date
     * @return "yyyy-M-d"
     */
    public static String formateDateSimple(Date date) {
        SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-M-d");
        if (date == null) {
            return "";
        }
        return dateformat.format(date);
    }

    /**
     * @param dateTime
     * @return "yyyy-MM-dd HH:mm:ss"
     */
    public static String formateDate(Long dateTime) {
        Date date = new Date();
        date.setTime(dateTime);
        return formateDate(date);
    }

    /**
     * @param dateTime
     * @return "yyyy-M-d"
     */
    public static String formateDateSimple(Long dateTime) {
        Date date = new Date();
        date.setTime(dateTime);
        return formateDateSimple(date);
    }

    /**
     * utc 时间转换成 本地时间
     *
     * @param utc
     * @return
     */
    @Deprecated
    public static Date UTCDate2Local(Date utc) {
        return new Date(utc.getTime() - 28800000);
    }

    @Deprecated
    public static long UTCDate2Local(long utc) {
        return utc - 28800000;
    }

    /**
     * 处理 null 字符串
     *
     * @param str
     * @return null 输出"", 否则输出 .trim()
     */
    public static String dealWithNullVal(String str) {
        if (str == null) {
            return "";
        } else {
            return str.trim();
        }
    }

    /**
     * 处理 null 字符串
     *
     * @param str
     * @return null 输出"", 否则输出 .trim()
     */
    public static String dealWithNullValStrObj(Object str) {
        if (str == null) {
            return "";
        } else {
            return str.toString().trim();
        }
    }

    /**
     * 处理 null 数字
     *
     * @param input
     * @return null 返回 0
     */
    public static Integer dealWithNullVal(Integer input) {
        if (input == null) {
            return 0;
        } else {
            return input;
        }
    }

    /**
     * 处理 null 数字
     *
     * @param input
     * @return null 返回 0d
     */
    public static Double dealWithNullVal(Double input) {
        if (input == null || input.isInfinite() || input.isNaN()) {
            return 0d;
        } else {
            return input;
        }
    }

    /**
     * 转换成 JSONObject, 目标属性不得有类类型
     *
     * @param mapinfo
     * @return
     */
    public static JSONObject convertInfo2JSON(HashMap<String, Object> mapinfo) {
        JSONObject obj = new JSONObject();
        ArrayList<String> keys = new ArrayList<String>();
        keys.addAll(mapinfo.keySet());

        for (String key : keys) {
            obj.put(key, mapinfo.get(key));
        }

        return obj;
    }

    /**
     * 加密
     *
     * @param rawPass
     * @return
     */
    public static String encodePassword(String rawPass) {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String encodePass = encoder.encode(rawPass);
        return encodePass;
    }

    /**
     * 对比秘钥
     *
     * @param rawPass
     * @param encodedPass
     * @return 成功返回true, 失败返回false
     */
    public static boolean compilePassword(String rawPass, String encodedPass) {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        return encoder.matches(rawPass, encodedPass);
    }

    /**
     * 程序返回结果转换成json字符串, 给提示框使用
     *
     * @param status 状态
     * @param data   显示内容
     * @return
     */
    public static String convert2JsonResult(String status, String data) {
        JSONObject res = new JSONObject();
        res.put("status", status);
        res.put("data", data);
        return res.toString();
    }

    /**
     * 程序返回结果转换成json字符串, 给提示框使用
     *
     * @param status 状态, 0:error, 1:success
     * @param data   显示内容
     * @return
     */
    public static String convert2JsonResult(Integer status, String data) {
        JSONObject res = new JSONObject();

        if (0 == status) {
            res.put("status", "error");
        } else if (1 == status) {
            res.put("status", "success");
        }

        res.put("data", data);
        return res.toString();
    }

    /**
     * 程序返回结果转换成json字符串, 给提示框使用
     *
     * @param status 状态
     * @param data   显示内容
     * @return
     */
    public static JSONObject convert2JsonResultRaw(String status, String data) {
        JSONObject res = new JSONObject();
        res.put("status", status);
        res.put("data", data);
        return res;
    }

    /**
     * 程序返回结果转换成json字符串, 给提示框使用
     *
     * @param status 状态, 0:error, 1:success
     * @param data   显示内容
     * @return
     */
    public static JSONObject convert2JsonResultRaw(Integer status, String data) {
        JSONObject res = new JSONObject();

        if (0 == status) {
            res.put("status", "error");
        } else if (1 == status) {
            res.put("status", "success");
        }

        res.put("data", data);
        return res;
    }

    /**
     * 去掉字符串中的所有空格，包括中间的
     */
    public static String delAllSpace(String target) {

        String res = "";
        for (int i = 0; i < target.length(); i++) {
            if ((target.charAt(i)) != ' ')
                res += target.charAt(i);
        }
        /*
         * while(!target.replaceAll(" ", "").equals(target)) target =
		 * target.replaceAll(" ", "");
		 */
        return res;
    }

    public static void ___printTimeLast(Calendar begin, String msg) {
        Logger.getLogger(JigeWebTools.class)
                .info(msg + " timelast: " + (Calendar.getInstance().getTimeInMillis() - begin.getTimeInMillis()) + " ms"
                );
    }

    /**
     * 修改map元素的类型,保证可以存入到mongodb
     * java.sql.Timestamp -> date
     *
     * @param datain
     * @return
     */
    public static Map<String, Object> changeDataType(Map<String, Object> datain) {
        for (String key : datain.keySet()) {
            if (datain.get(key) instanceof java.sql.Timestamp) {
                java.sql.Timestamp val = (Timestamp) datain.get(key);
                Calendar cal = Calendar.getInstance();
                cal.setTimeInMillis(val.getTime());
                datain.put(key, cal.getTime());
            }
        }
        return datain;
    }

    /**
     * 修改map元素的类型,保证可以存入到mongodb
     * java.sql.Timestamp -> date
     *
     * @param datain
     * @return
     */
    public static List<Map<String, Object>> changeDataType(List<Map<String, Object>> datain) {
        for (Map<String, Object> it : datain) {
            changeDataType(it);
        }
        return datain;
    }

    /**
     * "\\S*" + searchText.replace(" ", "+\\S*") + "+"
     *
     * @param searchText
     * @return
     */
    public static Pattern getSearchRegex(String searchText) {
        searchText = "\\S*" + searchText.trim().replace(" ", "+\\S*") + "+";
        return Pattern.compile(searchText);
    }

    /**
     * 辅助工具 将字符串数组转换成list (有判断 null "")
     *
     * @param valarr
     * @return
     */
    public static List<String> parseArr2List(String[] valarr) {
        ArrayList<String> valList = new ArrayList<>();
        for (String val : valarr) {
            if (val != null && !val.isEmpty()) {
                valList.add(val);
            }
        }
        return valList;
    }

    /**
     * 辅助工具 将字符串数组转换成list (有判断 null "")
     *
     * @param valarr
     * @return
     */
    public static List<Integer> parseArr2List(Integer[] valarr) {
        ArrayList<Integer> valList = new ArrayList<>();
        for (Integer val : valarr) {
            if (val != null) {
                valList.add(val);
            }
        }
        return valList;
    }

    public static String sendHttpGet(String url) throws Exception {
        URL urls = new URL(url);
        HttpURLConnection uc = (HttpURLConnection) urls.openConnection();
        uc.setRequestMethod("GET");
        uc.setRequestProperty("content-type",
                "text/plain");
        uc.setRequestProperty("charset", "UTF-8");
//            uc.setDoOutput(true);
        uc.setDoInput(true);
        uc.setReadTimeout(30000);
        uc.setConnectTimeout(30000);
//            OutputStream os = uc.getOutputStream();
//            DataOutputStream dos = new DataOutputStream(os);
//            dos.write(message.getBytes("utf-8"));
//            dos.flush();
//            os.close();
        BufferedReader in = new BufferedReader(new InputStreamReader(uc
                .getInputStream(), "utf-8"));
        String readLine = "";
        StringBuilder sb = new StringBuilder();
        while ((readLine = in.readLine()) != null) {
            sb.append(readLine);
        }
        in.close();
        return sb.toString();
    }

    public static String sendHttpPost(String url, Map<String, String> params) throws Exception {

        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");

        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        for (String key : params.keySet()) {
            nvps.add(new BasicNameValuePair(key, params.get(key)));
        }
        httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));
        CloseableHttpResponse response2 = httpclient.execute(httpPost);
        String res = "";
        try {
            HttpEntity entity2 = response2.getEntity();
            // do something useful with the response body
            // and ensure it is fully consumed
            res = readRes(entity2.getContent());
            EntityUtils.consume(entity2);
        } catch (Exception e) {
            throw e;
        } finally {
            response2.close();
        }
        return res;
    }

    public static String readRes(java.io.InputStream inputStream) throws Exception {
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
        String readLine = "";
        StringBuilder sb = new StringBuilder();
        while ((readLine = in.readLine()) != null) {
            sb.append(readLine);
        }
        in.close();
        return sb.toString();
    }

    /**
     * 从jsonobj里面取属性 null或者没有这个属性返回null 字符串返回.trim()
     *
     * @param obj
     * @param paramName
     * @return
     */
    public static Object getJsonObjParam(JSONObject obj, String paramName) {
        if (obj.has(paramName)) {
            Object param = obj.get(paramName);
            if (param instanceof String) {
                return obj.getString(paramName).trim();
            }
            if (param.equals(JSONObject.NULL)) {
                return null;
            }
            return param;
        }
        return null;
    }

    /**
     * 清除掉所有特殊字符
     *
     * @param str
     * @return
     * @throws Exception
     */
    public static String stringFilter_noSpeicalChar(String str) throws Exception {
        String regEx = "[\"`~!@#$%^&*()+=|{}':;',//[//].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        return m.replaceAll("").trim();
    }

    /**
     * 获取当前登录的用户的用户名
     *
     * @return
     */
    static public String getCurrentUsername() {
        String username = "";
        if (SecurityContextHolder.getContext().getAuthentication() != null) {
            Object userDetails = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

            if (userDetails instanceof UserDetails) {
                username = ((UserDetails) userDetails).getUsername();
            } else if (userDetails instanceof String) {
                username = (String) userDetails;
            }

        }
        return username;
    }
}
